import java.util.NoSuchElementException;

public class ArrayQueue<E> implements IQueue<E> {
	private E[] internalArray;
	private int posOfHead;
	private int filling;
	private int capacity;

	public ArrayQueue() {
		this(16);

	}

	public ArrayQueue(int capacity) {
		this.internalArray = (E[]) new Object[capacity];
		this.capacity = capacity;
		this.posOfHead = - 1;
		this.filling = 0;
	}

	@Override
	public boolean offer(E element) {
		if ( element == null ) {
			throw new NullPointerException();
		} else if ( filling == capacity ) {
			normalizeCapacity();
		}
		if ( posOfHead == - 1 ) {
			posOfHead++;
			filling = 0;
		}
		internalArray[filling++] = element;
		return true;
	}


	@Override
	public E element() {
		E result = peek();
		if ( result == null ) {
			throw new NoSuchElementException();
		}
		return result;
	}


	@Override
	public E peek() {
		if ( posOfHead >= 0 ) {
			return internalArray[posOfHead];
		} else {
			return null;
		}
	}

	@Override
	public E poll() {
		if ( posOfHead != - 1 ) {
			if ( filling - posOfHead == 1 ) {
				E result = internalArray[posOfHead];
				filling = 0;
				posOfHead = - 1;
				return result;
			} else if ( filling - posOfHead > 1 ) {
				E result = internalArray[posOfHead];
				posOfHead++;
				return result;
			}
		}
		return null;

	}

	@Override
	public E remove() {
		E result = poll();
		if ( result == null ) {
			throw new NoSuchElementException();
		}
		return result;
	}


	private void normalizeCapacity() {
		if ( posOfHead == - 1 ) {
			internalArray = (E[]) new Object[16];
			this.capacity = 16;
			this.filling = 0;
		} else {
			filling = capacity - posOfHead;
			capacity = filling * 3 / 2;
			posOfHead = 0;

			E[] newArray = (E[]) new Object[capacity];
			System.arraycopy(internalArray, posOfHead, newArray, 0, internalArray.length - posOfHead);
			internalArray = newArray;

		}
	}
}
